/* 
 *	Copyright 2014  Yanqing Wu
 *		email: yqwu_yqwu@126.com
 *
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
*/

#include "stdafx.h"
#include "StdCtrlSkinCell.h"
#include "StdCtrlSkinRow.h"

#include "StdCtrlSkinTool_Utils.h"


void CStdCtrlSkinCell::InitDataElt(CStdCtrlSkinRow* pRow)
{
	rowspan = 1;
	colspan = 1;
	m_pRow = pRow;
}

CStdCtrlSkinCell::CStdCtrlSkinCell(CStdCtrlSkinRow* pRow)
{
	InitDataElt(pRow);
}
CStdCtrlSkinCell::CStdCtrlSkinCell(CComPtr<IXMLDOMNode> spNode, CStdCtrlSkinRow* pRow)
{
	InitDataElt(pRow);
	LoadXmlNode(spNode);
}

CStdCtrlSkinCell::~CStdCtrlSkinCell(void)
{
}

CString CStdCtrlSkinCell::GetFilePath(void)
{
	return m_pRow->GetFilePath();
}

bool CStdCtrlSkinCell::LoadXmlNode(CComPtr<IXMLDOMNode> spNode)
{
	auto attribPairs = StdCtrlSkinTool_XmlGetAttribPairs(spNode);
	auto pEnum = StdCtrlSkinTool_GetEnum();
	for(auto i : attribPairs)
	{
		auto name = i.first;
		auto value = i.second;
		CStdCtrlSkin_EnumAttrib attr;
		bool correct = pEnum->Parse(attr, name);
		if ( !correct )
			continue;
		switch(attr)
		{
		case CStdCtrlSkin_EnumAttrib::NAME:
			ctrl_id = value;
			break;
		case CStdCtrlSkin_EnumAttrib::WIDTH:
			attrib.width = StdCtrlSkinTool_CString2Long(value);
			break;
		case CStdCtrlSkin_EnumAttrib::HEIGHT:
			attrib.height = StdCtrlSkinTool_CString2Long(value);
			break;
		case CStdCtrlSkin_EnumAttrib::PADX:
			attrib.padx = StdCtrlSkinTool_CString2Long(value);
			break;
		case CStdCtrlSkin_EnumAttrib::PADY:
			attrib.pady = StdCtrlSkinTool_CString2Long(value);
			break;
		case CStdCtrlSkin_EnumAttrib::ROWSPAN:
			rowspan = StdCtrlSkinTool_CString2Long(value);
			break;
		case CStdCtrlSkin_EnumAttrib::COLSPAN:
			colspan = StdCtrlSkinTool_CString2Long(value);
			break;
		case CStdCtrlSkin_EnumAttrib::STICKY:
			pEnum->ParseCombo(attrib.sticky, value);
			break;
		default:
			break;
		}
	}
	return true;
}

CStdCtrlSkinAttrib CStdCtrlSkinCell::GetAttribFinal(void)
{
	auto resDef = m_pRow->GetAttribFinal(col);
	return StdCtrlSkinTool_MergeAttrib(attrib, resDef);
}

UINT CStdCtrlSkinCell::GetMinWidth(void)
{
	auto attribFinal = GetAttribFinal();
	return attribFinal.width + attribFinal.padx * 2;
}
UINT CStdCtrlSkinCell::GetMinHeight(void)
{
	auto attribFinal = GetAttribFinal();
	return attribFinal.height + attribFinal.pady * 2;
}

CRect CStdCtrlSkinCell::GetCellRect(void)
{
	CRect rect;
	rect.left = m_pRow->GetColStart(col);
	rect.right = m_pRow->GetColEnd(col+colspan-1);
	rect.top = m_pRow->GetRowStart();
	rect.bottom = m_pRow->GetRowEnd(m_pRow->row + rowspan-1);
	return rect;
}

CRect CStdCtrlSkinCell::GetCtrlRect(void)
{
	auto rect = GetCellRect();
	auto attribFinal = GetAttribFinal();
	int iSticky = (int)attribFinal.sticky;
	//	Get left and right side, check for w/e sticky
	if ( iSticky & (int)CStdCtrlSkin_EnumSticky::W )
	{
		//	sticky to left
		rect.left += attribFinal.padx;
		if ( iSticky & (int)CStdCtrlSkin_EnumSticky::E )
		{
			//	also sticky to right
			rect.right -= attribFinal.padx;
		}
		else
			rect.right = rect.left + attribFinal.width;
	}
	else if ( iSticky & (int)CStdCtrlSkin_EnumSticky::E )
	{
		//	sticky to right only
		rect.right -= attribFinal.padx;
		rect.left = rect.right - attribFinal.width;
	}
	else
	{
		//	at center
		auto middle = (rect.left + rect.right) / 2;
		rect.left = middle - attribFinal.width / 2;
		rect.right = rect.left + attribFinal.width;
	}
	//	Get top and bottom side, same method as left/right
	if ( iSticky & (int)CStdCtrlSkin_EnumSticky::N )
	{
		rect.top += attribFinal.pady;
		if ( iSticky & (int)CStdCtrlSkin_EnumSticky::S )
			rect.bottom -= attribFinal.pady;
		else
			rect.bottom = rect.top + attribFinal.height;
	}
	else if ( iSticky & (int)CStdCtrlSkin_EnumSticky::S )
	{
		rect.bottom -= attribFinal.pady;
		rect.top = rect.bottom - attribFinal.height;
	}
	else
	{
		auto middle = (rect.top + rect.bottom) / 2;
		rect.top = middle - attribFinal.height / 2;
		rect.bottom = rect.top + attribFinal.height;
	}
	return rect;
}

#ifdef __DUMPTEST
void CStdCtrlSkinCell::Dump(std::ofstream& fio, CStdCtrlSkin_EnumDump type)
{
	auto dumpCell = (CStdCtrlSkin_EnumDump)(
		(int)CStdCtrlSkin_EnumDump::CELL_RECT |
		(int)CStdCtrlSkin_EnumDump::CELL_ITEM_RECT |
		(int)CStdCtrlSkin_EnumDump::CELL_ATTRIB_INST |
		(int)CStdCtrlSkin_EnumDump::CELL_ATTRIB_FINAL
		);
	if ( !((int)type & (int)dumpCell) )
		return;
	fio << "Cell (" << m_pRow->row << "," << col << ") info\n";
	CStringA nameA(ctrl_id);
	auto pEnum = StdCtrlSkinTool_GetEnum();
	auto skickyStr = pEnum->ComboToString(attrib.sticky);
	CStringA stickyA(skickyStr);
	fio << "\tControlID=" << nameA.GetString() << " width=" << attrib.width << " height=" << attrib.height
		<< " padx=" << attrib.padx << " pady=" << attrib.pady << " colspan=" << colspan << " rowspan=" << rowspan
		<< " sticky=" << stickyA.GetString()
		<< std::endl;
	DumpCellRect(fio, type);
	DumpCtrlRect(fio, type);
	DumpCellAttribInst(fio, type);
	DumpCellAttribFinal(fio, type);
}
#endif

void CStdCtrlSkinCell::DumpCellRect(std::ofstream& fio, CStdCtrlSkin_EnumDump type)
{
	if ( !((int)type & (int)CStdCtrlSkin_EnumDump::CELL_RECT) )
		return;
	fio << "  Cell Rect\n";
	auto rect = GetCellRect();
	fio << "\t(" << rect.left << "," << rect.top << ")-(" << rect.right << "," << rect.bottom
		<< ")\n";
}
void CStdCtrlSkinCell::DumpCtrlRect(std::ofstream& fio, CStdCtrlSkin_EnumDump type)
{
	if ( !((int)type & (int)CStdCtrlSkin_EnumDump::CELL_ITEM_RECT) )
		return;
	fio << "  Control Rect\n";
	auto rect = GetCtrlRect();
	fio << "\t(" << rect.left << "," << rect.top << ")-(" << rect.right << "," << rect.bottom
		<< ")\n";
}
void CStdCtrlSkinCell::DumpCellAttribInst(std::ofstream& fio, CStdCtrlSkin_EnumDump type)
{
	if ( !((int)type & (int)CStdCtrlSkin_EnumDump::CELL_ATTRIB_INST) )
		return;
	fio << "  Instance attributes\n";
	auto pEnum = StdCtrlSkinTool_GetEnum();
	auto stickyStr = pEnum->ComboToString(attrib.sticky);
	CStringA stickyA(stickyStr);
	fio << "\twidth=" << attrib.width << " height=" << attrib.height << " padx=" << attrib.padx
		<< " pady=" << attrib.pady << " sticky=" << stickyA.GetString() << std::endl;
}
void CStdCtrlSkinCell::DumpCellAttribFinal(std::ofstream& fio, CStdCtrlSkin_EnumDump type)
{
	if ( !((int)type & (int)CStdCtrlSkin_EnumDump::CELL_ATTRIB_FINAL) )
		return;
	auto attrF = GetAttribFinal();
	fio << "  Final attributes\n";
	auto pEnum = StdCtrlSkinTool_GetEnum();
	auto stickyStr = pEnum->ComboToString(attrF.sticky);
	CStringA stickyA(stickyStr);
	fio << "\twidth=" << attrF.width << " height=" << attrF.height << " padx=" << attrF.padx
		<< " pady=" << attrF.pady << " sticky=" << stickyA.GetString() << std::endl;
}
